package com.richie696.connect.http11;

import com.richie696.catalina.*;
import com.richie696.catalina.connector.Connector;

import java.io.InputStream;
import java.net.Socket;
import java.util.List;
import java.util.Objects;

public class Http11BioProtocol extends AbstractHttp11Protocol {

    @Override
    public void start(Connector connector, Socket socket) throws Exception {
        InputStream inputStream = socket.getInputStream();
        // 等待输入流的数据可用。
        int count = 0;
        while (count == 0) {
            count = inputStream.available();
            Thread.sleep(100);
        }
        byte[] bytes = new byte[count];
        int res;
        do {
            res = inputStream.read(bytes);
        } while (res < count);
        String content = new String(bytes);
        Header header = getHeader(content);
        HttpServletRequest request = new ApplicationHttpRequest(inputStream, header);
        Engine engine = connector.getEngine();
        Host host = engine.getHost(request.getRemoteHost());
        if (Objects.isNull(host)) {
            host = engine.getDefaultHost();
        }
        if (Objects.isNull(host)) {
            throw new LifecycleException("默认主机配置无效。defaultHost = " + engine.getDefaultHostName());
        }
        List<Wrapper> wrappers = host.getWrappers();
        Wrapper wrapper = wrappers.stream().filter(w ->
                header.getUrl().startsWith(w.getName())).findFirst().orElse(host.getDefaultWrapper());
        ApplicationHttpResponse response = new ApplicationHttpResponse(socket.getOutputStream(), wrapper.getWarAbstractPath());
        ServletMapping servletMapping = wrapper.getServletMappingByUrl(header.getUrl());
        if (Objects.isNull(servletMapping)) {
            response.getOutputStream().write(HttpProtocolUtil.getHttpHeader404().getBytes());
            response.getOutputStream().flush();
            return;
        }
        Servlet servlet = servletMapping.getServlet();
        if (Objects.isNull(servlet)) {
            try {
                @SuppressWarnings("unchecked")
                Class<?> cls = wrapper.getWebAppClassLoader().findClass(servletMapping.getServletClass());
                servlet = (Servlet) cls.getConstructor().newInstance();
                servletMapping.setServlet(servlet);
            } catch (Exception e) {
                response.getOutputStream().write(HttpProtocolUtil.getHttpHeader404().getBytes());
                response.getOutputStream().flush();
                return;
            }
        }
        servlet.init();
        servlet.service(request, response);
        inputStream.close();
    }

}
